package data

import (
	"context"
	"time"

	"entgo.io/ent/entc/integration/config/ent"
	pberr "gitee.com/zhangxinzx/notebook/api/notebook/v1"
	"gitee.com/zhangxinzx/notebook/internal/biz"
	"gitee.com/zhangxinzx/notebook/internal/data/ent/note"
	"github.com/go-kratos/kratos/v2/log"
)

type noteRepo struct {
	data *Data
	log  *log.Helper
}

func NewNoteRepo(data *Data, logger log.Logger) biz.NoteRepo {
	return &noteRepo{
		data: data,
		log:  log.NewHelper(logger),
	}
}

func (nr *noteRepo) CreateNote(ctx context.Context, note *biz.Note) error {
	if note.CategoryID == 0 {
		note.CategoryID = defaultCategoryID
	}
	err := nr.data.db.Note.Create().
		SetTitle(note.Title).
		SetContent(note.Content).
		SetCategoriesID(note.CategoryID).Exec(ctx)

	if err != nil {
		return pberr.ErrorServerInternal("create note title [ %s ]", note.Title)
	}

	return nil
}

func (nr *noteRepo) GetNote(ctx context.Context, id int64) (*biz.Note, error) {
	note, err := nr.data.db.Note.Get(ctx, id)
	if err != nil && ent.IsNotFound(err) {
		return nil, pberr.ErrorNoteNotFound("note id [ %d ] not found", id)
	} else if err != nil {
		return nil, pberr.ErrorServerInternal("get note id [ %d ] failed", id)
	}

	return &biz.Note{
		ID:        note.ID,
		Title:     note.Title,
		Content:   note.Content,
		CreatedAt: note.CreatedAt,
		UpdatedAt: note.UpdatedAt,
	}, nil
}

func (nr *noteRepo) UpdateNote(ctx context.Context, id int64, nt *biz.Note) error {
	n, err := nr.data.db.Note.Query().Where(note.ID(id)).Only(ctx)
	if err != nil && ent.IsNotFound(err) {
		return pberr.ErrorNoteNotFound("note id [ %d ] is not found", id)
	} else if err != nil {
		return pberr.ErrorServerInternal("get note id [ %d ] failed", id)
	}

	err = n.Update().
		SetTitle(nt.Title).
		SetContent(nt.Content).
		SetUpdatedAt(time.Now()).Exec(ctx)
	if err != nil {
		return pberr.ErrorServerInternal("get note id [ %d ] failed", id)
	}

	return nil
}

func (nr *noteRepo) MoveNote(ctx context.Context, id int64, categoryID int64) error {
	n, err := nr.data.db.Note.Query().Where(note.ID(id)).Only(ctx)
	if err != nil && ent.IsNotFound(err) {
		return pberr.ErrorNoteNotFound("note id [ %d ] is not found", id)
	} else if err != nil {
		return pberr.ErrorServerInternal("get note id [ %d ] failed", id)
	}

	err = n.Update().SetCategoriesID(categoryID).Exec(ctx)

	return err
}

func (nr *noteRepo) DeleteNote(ctx context.Context, id int64) error {
	_, err := nr.data.db.Note.Delete().Where(note.ID(id)).Exec(ctx)
	if err != nil && ent.IsNotFound(err) {
		return pberr.ErrorNoteNotFound("note id [ %d ] is not found", id)
	} else if err != nil {
		return pberr.ErrorServerInternal("delete note id [ %d ] failed")
	}

	return nil
}
